package com.atwisdom.star.core.dsl.modelClass.hier.Impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.atwisdom.star.common.enums.RoutingStatusEnum;
import com.atwisdom.star.common.enums.WorkCenterInnerStatusEnum;
import com.atwisdom.star.common.util.JsonUtil;
import com.atwisdom.star.common.util.UuidTool;
import com.atwisdom.star.common.vo.ModelType;
import com.atwisdom.star.common.vo.StatusCode;
import com.atwisdom.star.core.dao.pojo.modelClass.hier.HierInstance;
import com.atwisdom.star.core.dao.pojo.modelClass.hier.HierInstanceHistory;
import com.atwisdom.star.core.dao.pojo.modelClass.hier.HierModel;
import com.atwisdom.star.core.dao.service.modelClass.hier.HierInstanceHistoryService;
import com.atwisdom.star.core.dao.service.modelClass.hier.HierInstanceService;
import com.atwisdom.star.core.dao.service.modelClass.hier.HierModelService;
import com.atwisdom.star.core.dao.util.DaoUtil;
import com.atwisdom.star.core.dsl.cache.ModelCacheDslService;
import com.atwisdom.star.core.dsl.modelClass.hier.HierInstanceDslService;
import com.atwisdom.star.core.dsl.modelClass.utils.QueryBuilder;
import com.atwisdom.star.exception.pojo.BusinessException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.*;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
@Slf4j
@AllArgsConstructor
public class HierInstanceDslServiceImpl implements HierInstanceDslService {
    private HierInstanceService hierInstanceService;
    private HierModelService hierModelService;
    private HierInstanceHistoryService hierInstanceHistoryService;
    private QueryBuilder queryBuilder;
    private ModelCacheDslService modelCacheDslService;


    @Override
    public List<HierInstance> add(JSONObject hierProperties) {
        List<HierInstance> instanceList = buildInstanceList(hierProperties);
        hierInstanceService.saveBatch(instanceList);
        addHistory(instanceList);
        return instanceList;
    }

    /**
     * 完全复制Model创建的实例
     * @param containerModel
     * @param className
     * @param containerId
     * @return
     */
    @Override
    public List<HierInstance> add(String containerModel, String className, Long containerId) {
        List<HierInstance> instanceList = buildInstanceList(containerModel, className, containerId);
        if (CollectionUtil.isNotEmpty(instanceList)) {
            hierInstanceService.saveOrUpdateBatch(instanceList);
            addHistory(instanceList);
        }
        return instanceList;
    }

    /**
     * 为指定实例的指定节点，添加下级数据
     * 如果当前parentId的model中有属性，则拿到当前Model属性，如果没有，逐级往上查找，直到root为止，取最近一个节点的properties作为模型，往指定节点下添加数据
     * @param model
     * @param className
     * @param containerId
     * @param dataJsonList
     * @return
     */
    @Override
    public List<HierInstance> addChild(String model, String className, Long containerId, String parentNodeId, List<JSONObject> dataJsonList) {
        List<HierInstance> instanceList = buildChildInstanceList(model, className, containerId, parentNodeId, dataJsonList);
        if (CollectionUtil.isNotEmpty(instanceList)) {
            hierInstanceService.saveOrUpdateBatch(instanceList);
            addHistory(instanceList);
        }
        return instanceList;
    }

    /**
     *
     * @param containerId
     * @param hierModelList 必须为一组
     * @return
     */
    @Override
    public List<HierInstance> add(Long containerId, List<HierModel> hierModelList) {
        List<HierInstance> instanceList = new ArrayList<>();
        hierModelList.forEach(hierModel->{
            instanceList.add(buildNewInstanceFromModel(containerId, hierModel));
        });
        hierInstanceService.saveOrUpdateBatch(instanceList);
        addHistory(instanceList);
        return instanceList;
    }

    /**
     *
     * @param containerId
     * @param hierModel
     * @return
     */
    @Override
    public HierInstance add(Long containerId, HierModel hierModel) {
        HierInstance hierInstance = buildNewInstanceFromModel(containerId, hierModel);
        hierInstanceService.saveOrUpdate(hierInstance);
        addHistory(Arrays.asList(hierInstance));
        return hierInstance;
    }

    /**
     * 处理需要新增的数据
     * @param hierModelMap
     */
    private void handleNeedAddInstance(Map<String, HierModel> hierModelMap) {
        List<HierInstance> addHierInstanceList = new ArrayList<>();
        // map中剩下的数据，就是需要新增的数据，但是新增的数据，没有containerId，如何处理？？目前设置为兄弟结点的containerId,兄弟节点也没有呢？可能是静态模型，去查询数据？静态模型是不是应该分model和instance了
        Collection<HierModel> addHierModelList = hierModelMap.values();
        addHierModelList.forEach(addHierModel -> {
            List<HierInstance> tempInstanceList = fetchByHierModel(addHierModel);
            Optional<HierInstance> brotherOption = tempInstanceList.stream().filter(d -> d.getParentId().equals(addHierModel.getParentId())).findFirst();
            if (brotherOption.isPresent()) {
                HierInstance brotherHierInstance = brotherOption.get();
                Long addContainerId = brotherHierInstance.getContainerId();
                HierInstance addHierInstance = buildNewInstanceFromModel(addContainerId, addHierModel);
                addHierInstanceList.add(addHierInstance);
            }
        });
        addBatch(addHierInstanceList);
    }

    /**
     * 处理原来已经存在的instance，更新或删除相应数据
     * @param hierModelMap
     * @param hierInstanceList
     */
    private void handleOriginInstance(Map<String, HierModel> hierModelMap, List<HierInstance> hierInstanceList) {
        List<HierInstance> updateHierInstanceList = new ArrayList<>();
        List<HierInstance> deleteHierInstanceList = new ArrayList<>();
        hierInstanceList.forEach(hierInstance -> {
            JSONObject hierJson = JsonUtil.toJSONObject(hierInstance);
            if (hierModelMap.containsKey(hierInstance.getNodeId())) {
                // Set<String> oldKeySet = hierJson.keySet();
                HierModel hierModel = hierModelMap.get(hierInstance.getNodeId());
                hierInstance = buildHierInstance(updateHierInstanceList, hierJson, hierModel);
            } else if(hierModelMap.containsKey(hierInstance.getParentId()) && "list".equals(hierModelMap.get(hierInstance.getParentId()).getNodeType())){
                HierModel hierModel = hierModelMap.get(hierInstance.getParentId());
                hierInstance = buildHierInstance(updateHierInstanceList, hierJson, hierModel);
            }else {
                deleteHierInstanceList.add(hierInstance);
            }
            hierModelMap.remove(hierInstance.getNodeId());
        });
        updateBatchById(updateHierInstanceList);
        hierInstanceService.removeBatchByIds(deleteHierInstanceList.stream().map(d->d.getId()).collect(Collectors.toList()));

    }

    private HierInstance buildHierInstance(List<HierInstance> updateHierInstanceList, JSONObject hierJson, HierModel hierModel) {
        Set<String> oldKeySet = hierJson.keySet();
        List<JSONObject> featureProperties = hierModel.fetchFeatureProperties();
        Map<String, JSONObject> codeMap = featureProperties.stream().collect(Collectors.toMap(fp -> fp.getString("code"), fp -> fp, (v1, v2) -> v2));
        oldKeySet.forEach(oldKey->{
            // 如果老的key在新的model中存在，则不用操作，如果不存在，则需要删除
            if (!codeMap.containsKey(oldKey)) {
                hierJson.remove(oldKey);
            }
            // 原来存在的key删除后，剩下的就是新的Model中新增的key，需要按默认值，添加到新的instance中
            codeMap.remove(oldKey);
        });
        Collection<JSONObject> needAddProperties = codeMap.values();
        needAddProperties.forEach(property->{
            hierJson.put(property.getString("code"), property.get("defaultValue"));
        });
        HierInstance hierInstance = JsonUtil.toJavaBean(hierJson, HierInstance.class);
        updateHierInstanceList.add(hierInstance);
        return hierInstance;
    }


    /**
     *
     * @param firstModel
     * @return
     */
    @Override
    public List<HierInstance> fetchByHierModel(HierModel firstModel) {
        return hierInstanceService.queryByModelAndClassName(firstModel.getModel(), firstModel.getClassName());
    }


    /**
     *
     * @param model
     * @param className
     * @return
     */
    @Override
    public List<HierInstance> fetchByModelAndClassName(String model, String className) {
        return hierInstanceService.queryByModelAndClassName(model, className);
    }

    /**
     * @param hierInstance
     * @return
     */
    @Override
    public HierInstance add(HierInstance hierInstance) {
        hierInstanceService.save(hierInstance);
        // addHistory(Arrays.asList(hierInstance));
        return hierInstance;
    }

    /**
     * @param hierInstanceList
     * @return
     */
    @Override
    public List<HierInstance> addBatch(List<HierInstance> hierInstanceList) {
        hierInstanceService.saveBatch(hierInstanceList);
//        addHistory(hierInstanceList);
        return hierInstanceList;
    }

    /**
     * @param parentHierInstance
     * @param linkId
     * @return
     */
    @Override
    public HierInstance addByParentHierInstance(HierInstance parentHierInstance, Long linkId) {
        HierInstance hierInstance = BeanUtil.copyProperties(parentHierInstance, HierInstance.class);
        hierInstance.setId(null);
        hierInstance.setParentId(parentHierInstance.getNodeId());
        hierInstance.setLinkId(linkId);
        hierInstance.setNodeId(UuidTool.getUUID32());
        hierInstance.setNodeType("leaf");
        hierInstance.setSt1(WorkCenterInnerStatusEnum.INNER.getCode());
        return add(hierInstance);
    }

    public List<HierInstance>  buildInstanceList(String containerModel, String className, Long containerId) {
        List<HierModel> hierModelList = hierModelService.queryByModelAndClassName(containerModel, className);
        List<HierInstance> resultList= buildNewInstanceFromModel(hierModelList, containerId);
        resultList.forEach(d->{
            if (StrUtil.isBlank(d.getName())) {
                d.setName(UuidTool.getUUID32());
            }
        });
       return resultList;
    }

    /**
     * @param containerModel
     * @param className
     * @param containerId
     * @param parentNodeId
     * @param dataJsonList 主要是values 和 LinkId 的不同
     * @return
     */
    public List<HierInstance>  buildChildInstanceList(String containerModel, String className, Long containerId, String parentNodeId,
            List<JSONObject> dataJsonList) {
        List<HierModel> hierModelList = hierModelService.queryByModelAndClassName(containerModel, className);
        HierModel parentModel = hierModelList.stream().filter(d -> d.getNodeId().equals(parentNodeId)).findFirst().get();
        HierModel finalHierPropertyModel = fetchFirstHierModelWithProperty(containerModel, className, parentNodeId);
        List<HierInstance> hierInstanceList = dataJsonList.stream().map(d -> buildNewInstanceFromModel(containerId, finalHierPropertyModel, parentModel, d))
                .collect(Collectors.toList());
        return hierInstanceList;
    }

    /**
     * 从当前Model逐级往上查找，找到最近一个带properties的Model
     * @param model
     * @param className
     * @param parentNodeId 查找的起始位置
     * @return
     */
    @Override
    public HierModel fetchFirstHierModelWithProperty(String model, String className, String parentNodeId) {
        List<HierModel> hierModelList = hierModelService.queryByModelAndClassName(model, className);
        if (CollectionUtil.isEmpty(hierModelList)) {
            return null;
        }
        // 先查找当前节点
        HierModel currentModel = hierModelList.stream().filter(d -> d.getNodeId().equals(parentNodeId)).findFirst().orElse(null);
        // 为了防止只有一个节点，但nodeId不为root的情况出现
        if (currentModel == null && hierModelList.size() == 1) {
            currentModel = hierModelList.get(0);
        }
        if (currentModel == null) {
            currentModel = hierModelList.stream().filter(d -> d.getNodeId().equals("root")).findFirst().orElse(null);
        }
        // System.out.println(1/0);
        while (currentModel.getProperties().isEmpty() && !currentModel.getNodeId().equals("root")) {
            HierModel finalHierModel = currentModel;
            currentModel = hierModelList.stream().filter(d -> d.getNodeId().equals(finalHierModel.getParentId())).findFirst().get();
        }
        if (currentModel.getProperties().isEmpty()) {
            log.info("指定的节点{},包括所有上级节点，没有属性定义", currentModel);
        }
        return currentModel;
    }

    /**
     * 从当前Model逐级往上查找，找到最近一个带properties的Model
     * @param hierInstance
     * @return
     */
    @Override
    public HierModel fetchFirstHierModelWithProperty(HierInstance hierInstance) {
        String model = hierInstance.getContainerModel();
        String className = hierInstance.getClassName();
        String nodeId = hierInstance.getNodeId();
        String parentNodeId = hierInstance.getParentId();
        // 为了防止有时参数中的hierInstance信息不全的情况
        if (StrUtil.isBlank(className)) {
            hierInstance = hierInstanceService.getById(hierInstance.getId());
        }
        List<HierModel> hierModelList = hierModelService.queryByModelAndClassName(model, className);
        if (CollectionUtil.isEmpty(hierModelList)) {
            return null;
        }
        // 先查找当前节点
        HierModel currentModel = null;
        if ("list".equals(hierInstance.getType())) {
            currentModel = hierModelList.get(0);
        } else {
            currentModel = hierModelList.stream().filter(d -> d.getNodeId().equals(nodeId)
            ).findFirst().orElse(null);
            // 为了防止只有一个节点，但nodeId不为root的情况出现
            if (currentModel == null && hierModelList.size() == 1) {
                currentModel = hierModelList.get(0);
            }
            if (currentModel == null) {
                currentModel = hierModelList.stream().filter(d -> d.getNodeId().equals(parentNodeId)).findFirst().orElse(null);
            }
            if (currentModel == null) {
                currentModel = hierModelList.stream().filter(d -> d.getNodeId().equals("root")).findFirst().orElse(null);
            }
            while (currentModel != null && (currentModel.getProperties().isEmpty() && !currentModel.getNodeId().equals("root"))) {
                HierModel finalHierModel = currentModel;
                currentModel = hierModelList.stream().filter(d -> d.getNodeId().equals(finalHierModel.getParentId())).findFirst().get();
            }
        }
        if (currentModel == null) {
            log.info("指定的节点没有上级节点");
        } else if (currentModel.getProperties().isEmpty()) {
            log.info("指定的节点{},包括所有上级节点，没有属性定义", currentModel);
        }
        return currentModel;
    }

    private  List<HierInstance> buildNewInstanceFromModel(List<HierModel> hierModelList, Long containerId) {
        return hierModelList.stream().map(
                hierModel -> buildNewInstanceFromModel(containerId, hierModel)).collect(Collectors.toList());
    }

    public HierInstance buildNewInstanceFromModel(Long containerId, HierModel hierModel) {
        JSONObject instanceJson = BeanUtil.copyProperties(hierModel, JSONObject.class);
        List<JSONObject> featureProperties = hierModel.fetchFeatureProperties();
        featureProperties.forEach(f->instanceJson.put(f.getString("code"), f.get("defaultValue")));
        HierInstance hierInstance = JsonUtil.toJavaBean(instanceJson, HierInstance.class);
        JSONObject nonFeatureValues = hierModel.fetchNonFeatureValues();
        hierInstance.setValues(nonFeatureValues);
        hierInstance.setId(null);
        hierInstance.setContainerId(containerId);
        hierInstance.setContainerModel(hierModel.getModel());
        hierInstance.setLinkId(hierModel.getLinkId());
        return hierInstance;
    }

    /**
     * @param containerId
     * @param hierPropertyModel
     * @param parentModel
     * @param dataJson
     * @return
     */
    public HierInstance buildNewInstanceFromModel(Long containerId, HierModel hierPropertyModel, HierModel parentModel, JSONObject dataJson) {
        JSONObject instanceJson = new JSONObject();
        JSONObject hierValuesJson = dataJson.getJSONObject("hierValues");
        if (hierValuesJson != null && hierValuesJson.size() > 0) {
            List<JSONObject> featureProperties = hierPropertyModel.fetchFeatureProperties();
            featureProperties.forEach(f->{
                Object filedValue = hierValuesJson.get(f.getString("name"));
                instanceJson.put(f.getString("code"), filedValue == null ? f.get("defaultValue") : filedValue);
                if (filedValue != null) {
                    hierValuesJson.remove(f.getString("name"));
                }
            });

        }
        // 执行到这里时，hierValuesJson 中剩下的全都是非查询字段
        JSONObject nonFeatureValues = hierPropertyModel.fetchNonFeatureValues();
        JSONObject nonFeatureTypeJson = hierPropertyModel.fetchNonFeatureTypeProperties();
        hierValuesJson.forEach((k,v)->{
            Object newValue =DaoUtil.ConvertFieldData(hierValuesJson.getString(k), nonFeatureTypeJson.getString(k));;
            nonFeatureValues.put(k, newValue);
        });
        instanceJson.put("values", nonFeatureValues);
        if(StrUtil.isNotEmpty(dataJson.getString("id"))){
            instanceJson.put("id", dataJson.get("id"));
        }
        HierInstance hierInstance = JsonUtil.toJavaBean(instanceJson, HierInstance.class);
        hierInstance.setType(parentModel.getType());
        hierInstance.setClassName(parentModel.getClassName());
        String uuid32 = UuidTool.getUUID32();
        hierInstance.setName(hierValuesJson!= null && StrUtil.isNotBlank(hierValuesJson.getString("name"))?hierValuesJson.getString("name") : uuid32);
        hierInstance.setContainerId(containerId);
        hierInstance.setContainerModel(hierPropertyModel.getModel());
        hierInstance.setParentId(parentModel.getNodeId());
        hierInstance.setPrev(dataJson.getJSONArray("prev"));
        hierInstance.setNodeId(uuid32);
        hierInstance.setNodeType(StrUtil.isNotBlank(dataJson.getString("nodeType"))? dataJson.getString("nodeType") : "leaf");
        hierInstance.setLinkModel(StrUtil.isNotBlank(dataJson.getString("linkModel"))? dataJson.getString("linkModel"): parentModel.getLinkModel());
        hierInstance.setLinkClassName(StrUtil.isNotBlank(dataJson.getString("linkClassName"))? dataJson.getString("linkClassName"): parentModel.getLinkClassName());
        hierInstance.setLinkType(StrUtil.isNotBlank(dataJson.getString("linkType"))? dataJson.getString("linkType"): parentModel.getLinkType());
        hierInstance.setLinkId(dataJson.getLong("linkId"));
        return hierInstance;
    }

    /**
     * 获取默认values
     *
     * @return 返回结果
     */
    public JSONObject fetchValuesFromProperty(JSONArray properties) {
        JSONObject values = new JSONObject();
        for (Object item : properties) {
            JSONObject itemJson = JsonUtil.toJSONObject(item);
            String name = itemJson.getString("name");
            if(StringUtils.isNotBlank(name)){
                values.put(itemJson.getString("name"), itemJson.get("defaultValue"));
            }
        }
        return values;
    }


    @Override
    public boolean updateInnerStatus(Long id) {
       return updateInnerStatus(Arrays.asList(id));
    }

    @Override
    public boolean updateInnerStatus(List<Long> idList) {
       List<HierInstance> instanceList = buildLeaveStatusInstanceList(idList);
       return updateBatchById(instanceList);
    }

    private List<HierInstance> buildLeaveStatusInstanceList(List<Long> idList) {
        List<HierInstance> hierModelList = hierInstanceService.listByIds(idList);
        // 0表示在workCenter中， 1表示已移至其他容器
        hierModelList.forEach(d->d.setSt1(WorkCenterInnerStatusEnum.OUTER.getCode()));
        return hierModelList;
    }

    /**
     * 更新指定容器下的hier数据
     *
     * @return
     */
    @Override
    public List<HierInstance> updateByContainerId(String model, String className, Long containerId, JSONObject updateHierJson) {
        List<HierInstance> updateInstanceList = buildUpdateInstanceList(model, className, containerId, updateHierJson);
        return saveOrUpdateBatch(updateInstanceList);
    }

    private List<HierInstance> buildUpdateInstanceList(String model, String className, Long containerId, JSONObject updateHierJson) {
        List<HierInstance> newInstanceList = new ArrayList<>();
        List<HierModel> hierModelList = hierModelService.queryByModelAndClassName(model, className);
        // Map<String, HierModel> modelMap = hierModelList.stream().collect(Collectors.toMap(d -> d.getNodeId(), v -> v));
        List<HierInstance> originHierInstanceList = queryByContainerId(model, className, containerId);
        // HierInstance firstHierInstance = originHierInstanceList.get(0);
        Map<String, HierInstance> originHierInstanceMap = originHierInstanceList.stream().collect(Collectors.toMap(HierInstance::getNodeId, v -> v));
        // 根据nodeId进行关联
        Map<String, JSONObject> nodeMap = convertHierJsonToMap(updateHierJson);
        nodeMap.forEach((nodeId, hierInstance)->{
            HierInstance originHierInstance = originHierInstanceMap.get(nodeId);
            if (originHierInstance != null) {
                BeanUtil.copyProperties(hierInstance, originHierInstance);
                newInstanceList.add(originHierInstance);
            } else {
                hierInstance.put("className", className);
                hierInstance.put("containerId",containerId);
                hierInstance.put("containerModel",model);
                newInstanceList.add(JsonUtil.toJavaBean(hierInstance, HierInstance.class));
            }
        });
        // 需要删除没用的节点吗？如果不删除，那删除功能就不正常，如果删除，静态模型更新时，可能会丢数据。
        return newInstanceList;
    }

    /**
     * @param hierJson
     * @return Map<String, JSONObject>  key为nodeId, value为content数据
     */
    private Map<String, JSONObject> convertHierJsonToMap(JSONObject hierJson) {
        Map<String, JSONObject> nodeMap = new HashMap<>();
        JSONArray contentArray = hierJson.getJSONArray("content");
        for (int i = 0; i < contentArray.size(); i++) {
            JSONObject content = contentArray.getJSONObject(i);
            String nodeId = content.getString("nodeId");
            nodeMap.put(nodeId, content);
        }
        return nodeMap;
    }

    /**
     * 更新业务有3类
     * 1. 增加节点， 指在原来的数据中，没有相应的nodeId
     * 2. 更新节点， 指在原来的数据中，存在相同的nodeId
     * 3. 删除节点， 指在原来的数据中，在新的数据中没有的nodeId
     * 所以，更新业务分为
     * 1. 先构建三类数据
     * 2. 操作库，进行数据变动
     * 注意：
     * 1. 参数中的节点是否应该保存，完全依赖与新的Model， 与原Model无关
     * 2. 节点中的field或value属性的值，应该根据新model的属性重新创建，存在的字段赋予原来的值，尽量不参考原Model
     *
     * @param oldHierModelList 一次只能更新一个Model,即List中所有数据应该属于一个model(model与className相同)
     * @param newHierModelList
     *
     */

    @Override
    public void updateByModel(List<HierModel> oldHierModelList, List<HierModel> newHierModelList) {
        List<HierInstance> newInstanceList = buildUpdateInstanceList(oldHierModelList, newHierModelList);
        updateBatchById(newInstanceList);
    }

    /**
     * 删除实例数据
     * @param hierProperties
     */
    private void remove(JSONObject hierProperties) {
        String containerModel = hierProperties.getString("containerModel");
        String containerId = hierProperties.getString("containerId");
        String className = hierProperties.getString("className");
        LambdaQueryWrapper<HierInstance> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(HierInstance::getContainerModel, containerModel)
                .eq(HierInstance::getClassName, className)
                .eq(StrUtil.isNotBlank(containerId), HierInstance::getContainerId, containerId);
        hierInstanceService.remove(wrapper);
    }

    /**
     * 根据Id更新记录
     * @param hierInstance
     * @return
     */
    @Override
    public HierInstance updateById(HierInstance hierInstance) {
        hierInstance = buildHierInstanceToBean(hierInstance);
        boolean result = hierInstanceService.updateById(hierInstance);
        // addHistory(Arrays.asList(hierInstance));
        HierModel hierModel = fetchFirstHierModelWithProperty(hierInstance);
        return convertValuesByProperty(hierInstance, hierModel);
    }

    /**
     * 根据Id更新记录有null值
     * @param hierInstance
     * @return
     */
    @Override
    public HierInstance updateNullById(HierInstance hierInstance) {
        hierInstanceService.getBaseMapper().updateById(hierInstance);
        // addHistory(Arrays.asList(hierInstance));
        HierModel hierModel = fetchFirstHierModelWithProperty(hierInstance);
        return convertValuesByProperty(hierInstance, hierModel);
    }

    /**
     * 将hierInstance中的values字段，映射到具体的code上
     * @param hierInstance
     * @return
     */
    private HierInstance buildHierInstanceToBean(HierInstance hierInstance) {
        HierInstance originHierInstance = hierInstanceService.getById(hierInstance.getId());
        Assert.notNull(originHierInstance, "更新的数据不存在");
        CopyOptions copyOptions = new CopyOptions();
        copyOptions.setIgnoreProperties("values");
        copyOptions.setIgnoreNullValue(true);
        BeanUtil.copyProperties(hierInstance, originHierInstance, copyOptions);
        BeanUtil.copyProperties(originHierInstance, hierInstance, "values");
        JSONObject originHierInstanceNonFeatureValues = ObjectUtil.cloneByStream(originHierInstance.getValues());
        HierModel hierModel = fetchFirstHierModelWithProperty(originHierInstance);
        originHierInstance = convertValuesByProperty(originHierInstance, hierModel);
        JSONObject originHierValueJson = originHierInstance.getValues();
        JSONObject instanceJson = JsonUtil.toJSONObject(hierInstance);
        JSONObject hierValuesJson = hierInstance.getValues();
        List<JSONObject> featureProperties = hierModel.fetchFeatureProperties();
        featureProperties.forEach(f->{
            Object filedValue = hierValuesJson.get(f.getString("name"));
            instanceJson.put(f.getString("code"), filedValue == null ? originHierValueJson.get(f.getString("name")) : filedValue);
            if (filedValue != null) {
                hierValuesJson.remove(f.getString("name"));
            }
        });
        hierInstance = JsonUtil.toJavaBean(instanceJson, HierInstance.class);
        // 执行到这里时，hierValuesJson 中剩下的全都是非查询字段
        JSONObject nonFeatureValues = hierModel.fetchNonFeatureValues();
        // 复制原来的非查询字段
        BeanUtil.copyProperties(originHierInstanceNonFeatureValues, nonFeatureValues);
        JSONObject nonFeatureTypeJson = hierModel.fetchNonFeatureTypeProperties();
        hierValuesJson.forEach((k,v)->{
            Object newValue =DaoUtil.ConvertFieldData(hierValuesJson.get(k), nonFeatureTypeJson.getString(k));;
            nonFeatureValues.put(k, newValue);
        });
        // BeanUtil.copyProperties(hierValuesJson, nonFeatureValues);
        hierInstance.setValues(nonFeatureValues);
        return hierInstance;
    }

    private List<HierInstance> buildHierInstanceToBean(List<HierInstance> hierInstanceList){
        return hierInstanceList.stream().map(d-> buildHierInstanceToBean(d))
                .collect(Collectors.toList());
    }

    /**
     * 根据Id更新记录，并增加历史
     * @param hierInstanceList
     * @return
     */
    @Override
    public boolean updateBatchById(List<HierInstance> hierInstanceList) {
        List<HierInstance> updateList = buildHierInstanceToBean(hierInstanceList);
       boolean result = hierInstanceService.updateBatchById(updateList);
       // addHistory(hierInstanceList);
       return result;
    }

    @Override
    public  List<HierInstance> query(String model, String className, String condition, String orderBy) {
        condition = queryBuilder.transformOperator(condition);
        String parentId = getParentIdBy(condition);
        condition = transformConditionForHier(model, className, parentId, condition);
        orderBy = transformOrderByForHier(condition, className, orderBy);
        QueryWrapper<HierInstance> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(StringUtils.isNotBlank(model), "containerModel", model);
        queryWrapper.eq(StringUtils.isNotBlank(className), "className", className);
        queryWrapper.apply(StringUtils.isNotBlank(condition), condition);
        queryBuilder.buildOrderBy(queryWrapper, orderBy, "className");
        List<HierInstance> list = hierInstanceService.list(queryWrapper);
        List<HierInstance> resultList = convertValuesByProperty(list);
        return resultList;
    }

    /**
     * 根据 主model和主ClassName，关联model和关联ClassName 查询关联的hier数据，并不进行value处理转换
     * @param containerModel 主模型
     * @param className 主类名
     * @param parentId 父id
     * @param LinkModel 关联模型
     * @param LinkClassName 关联类名
     * @param linkId
     * @return 关联的hier数据
     */
    @Override
    public List<HierInstance> queryLink(String containerModel, String className,String parentId, String LinkModel, String LinkClassName, Long linkId) {
        QueryWrapper<HierInstance> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(StringUtils.isNotBlank(containerModel), "containerModel", containerModel);
        queryWrapper.eq(StringUtils.isNotBlank(className), "className", className);
        queryWrapper.eq(StringUtils.isNotBlank(parentId), "parentId", parentId);
        queryWrapper.eq(StringUtils.isNotBlank(LinkModel), "linkModel", LinkModel);
        queryWrapper.eq(StringUtils.isNotBlank(LinkClassName), "linkClassName", LinkClassName);
        queryWrapper.eq(null!=linkId, "linkId", linkId);
        List<HierInstance> list = hierInstanceService.list(queryWrapper);
        return list;
    }

    /**
     * 根据 主model和主ClassName，关联model和关联ClassName和关联Link 查询关联的hier数据，并不进行value处理转换
     * @param containerModel 主模型
     * @param LinkModel 关联模型
     * @param linkId 关联实例id
     * @return 关联的hier数据
     */
    @Override
    public List<HierInstance> queryLink(String containerModel, String LinkModel, Long linkId) {
        QueryWrapper<HierInstance> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(StringUtils.isNotBlank(containerModel), "containerModel", containerModel);
        queryWrapper.eq(StringUtils.isNotBlank(LinkModel), "linkModel", LinkModel);
        queryWrapper.eq(null!=linkId, "linkId", linkId);
        List<HierInstance> list = hierInstanceService.list(queryWrapper);
        return list;
    }

    @Override
    public  List<HierInstance> query(String model, String className, String condition) {
        return query(model, className, condition, null);
    }

    @Override
    public long count(String model, String className, String condition) {
//        QueryWrapper<HierInstance> queryWrapper = new QueryWrapper<>();
//        queryWrapper.eq(StringUtils.isNotBlank(model), "containerModel", model);
//        queryWrapper.eq(StringUtils.isNotBlank(className), "className", className);
//        queryWrapper.apply(StringUtils.isNotBlank(condition), condition);
//        return hierInstanceService.count(queryWrapper);
        String parentId = queryBuilder.getParentIdBy(condition);
        if (StringUtils.isBlank(parentId)) {
            parentId = "root";
        }
        return this.count(model, className, condition, parentId);
    }

    @Override
    public long count(String model, String className, String condition,String parentId) {
        condition = queryBuilder.transformOperator(condition);
        condition = transformConditionForHier(model, className, parentId, condition);
        QueryWrapper<HierInstance> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(StringUtils.isNotBlank(model), "containerModel", model);
        queryWrapper.eq(StringUtils.isNotBlank(className), "className", className);
        queryWrapper.apply(StringUtils.isNotBlank(condition), condition);
        return hierInstanceService.count(queryWrapper);
    }

    @Override
    public List<HierInstance> queryByContainerId(String model, String className, Long containerId) {
        QueryWrapper<HierInstance> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("containerModel", model);
        queryWrapper.eq("className", className);
        queryWrapper.eq( "containerId", containerId);
        List<HierInstance> list = hierInstanceService.list(queryWrapper);
        List<HierInstance> resultList = convertValuesByProperty(list);
        return resultList;
    }

    @Override
    public List<HierInstance> queryByContainerId(String model, Long containerId) {
        QueryWrapper<HierInstance> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("containerModel", model);
        queryWrapper.eq( "containerId", containerId);
        List<HierInstance> list = hierInstanceService.list(queryWrapper);
        List<HierInstance> resultList = convertValuesByProperty(list);
        return resultList;
    }

    @Override
    public List<HierInstance> queryByContainerId(String model, Long containerId, String className, String condition) {
        return queryByContainerId(model, containerId, className, condition, false);
    }

    @Override
    public List<HierInstance> queryByContainerId(String model, Long containerId, String className, String condition, boolean needRootFlag) {
        QueryWrapper<HierInstance> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("containerModel", model);
        queryWrapper.eq( StrUtil.isNotBlank(className), "className", className);
        queryWrapper.eq( containerId!= null, "containerId", containerId);
        String parentId = getParentIdBy(condition);
        condition = queryBuilder.transformOperator(condition);
        condition = transformConditionForHier(model, className, parentId, condition);
        if (StrUtil.isNotBlank(condition)) {
            condition = condition.replace("'$", "insValues->'$");
        }
        if (StrUtil.isNotBlank(condition)) {
            queryWrapper.apply(condition);
        }
        if (needRootFlag) {
            String orCondition = " ( containerModel = '"+model+"' AND className = '"+className+"' and containerId = "+containerId+" AND nodeId='root')";
            queryWrapper.or();
            queryWrapper.apply(orCondition);
        }

        List<HierInstance> list = hierInstanceService.list(queryWrapper);
        List<HierInstance> resultList = convertValuesByProperty(list);
        return resultList;
    }

    @Override
    public Page<HierInstance> pageByContainerId(String model, Long containerId, String className,
                                                String condition, boolean needRootFlag, long current, long size, String orderBy) {
        QueryWrapper<HierInstance> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("containerModel", model);
        queryWrapper.eq( StrUtil.isNotBlank(className), "className", className);
        queryWrapper.eq( containerId!= null, "containerId", containerId);
        String parentId = getParentIdBy(condition);
        condition = queryBuilder.transformOperator(condition);
        condition = transformConditionForHier(model, className, parentId, condition);
        if (StrUtil.isNotBlank(condition)) {
            condition = condition.replace("'$", "insValues->'$");
        }
        if (StrUtil.isNotBlank(condition)) {
            queryWrapper.apply(condition);
        }

        if (needRootFlag) {
            String orCondition = " ( containerModel = '"+model+"' AND className = '"+className+"' and containerId = "+containerId+" AND nodeId='root')";
            queryWrapper.or();
            queryWrapper.apply(orCondition);
        }
        if (StrUtil.isNotBlank(orderBy)) {
            orderBy = transformOrderByForHier(condition, className, orderBy);
            queryBuilder.buildOrderBy(queryWrapper, orderBy, "id");
        }
        Page<HierInstance> pageInfo = new Page<>(current, size);
        pageInfo = hierInstanceService.page(pageInfo, queryWrapper);
        List<HierInstance> list = pageInfo.getRecords();
        List<HierInstance> resultList = convertValuesByProperty(list);
        pageInfo.setRecords(resultList);
        return pageInfo;
    }

    /**
     * 按Id查询记录
     * @param id
     * @return
     */
    @Override
    public JSONObject queryById(Long id) {
        HierInstance hierInstance = getById(id);
        return convertValuesByProperty(hierInstance);
    }

    public HierInstance queryHierInsById(Long id) {
        return hierInstanceService.getById(id);
    }


    @Override
    public List<HierInstance> queryChildByContainerId(String model, String className, Long containerId, String parentId, String condition) {
        QueryWrapper<HierInstance> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(StrUtil.isNotBlank(model), "containerModel", model);
        queryWrapper.eq(StrUtil.isNotBlank(className), "className", className);
        queryWrapper.eq(StrUtil.isNotBlank(parentId), "parentId", parentId);
        queryWrapper.eq(containerId!= null, "containerId", containerId);
        condition = queryBuilder.transformOperator(condition);
        condition = transformConditionForHier(model, className, parentId, condition);
        if (StrUtil.isNotBlank(condition)) {
            queryWrapper.apply(condition);
        }
        List<HierInstance> list = hierInstanceService.list(queryWrapper);
        List<HierInstance> resultList = convertValuesByProperty(list);
        return resultList;
    }

    @Override
    public List<HierInstance> convertValuesByProperty(List<HierInstance> list) {
        List<HierInstance> resultList = list.stream().map(d -> {
            HierModel hierModel = fetchFirstHierModelWithProperty(d);
            HierInstance hierInstance = convertValuesByProperty(d, hierModel);
            return hierInstance;
        }).collect(Collectors.toList());
        return resultList;
    }

    /**
     * 将字段映射转为Json
     * @param hierInstance
     * @return
     */
    @Override
    public JSONObject convertValuesByProperty(HierInstance hierInstance) {
        if (hierInstance == null) {
            return null;
        }
        HierModel hierModel = fetchFirstHierModelWithProperty(hierInstance);
        HierInstance newHierInstance = convertValuesByProperty(hierInstance, hierModel);
        return JsonUtil.toJSONObject(newHierInstance);
    }


    @Override
    public List<HierInstance> convertValuesByProperty(List<HierInstance> hierInstanceList, HierModel hierModel){
        return hierInstanceList.stream().map(hierInstance -> convertValuesByProperty(hierInstance, hierModel)).collect(Collectors.toList());
    }

    /**
     * 根据模型获取实列信息
     * @param hierModel 工艺路线模型
     * @return 返回结果实例JsonObject信息
     */
    @Override
    public HierInstance convertValuesByProperty(HierInstance hierInstance, HierModel hierModel){
        JSONObject values = hierInstance.getValues();
        if(values==null){
            values = new JSONObject();
        }
        String instanceJson = JSONObject.toJSONStringWithDateFormat(hierInstance, "yyyy-MM-dd HH:mm:ss", SerializerFeature.WriteDateUseDateFormat);
        JSONObject theJsonObject = JSONObject.parseObject(instanceJson);
        if(hierModel != null && hierModel.getProperties()!=null){
            List<JSONObject> featureProperties = hierModel.fetchFeatureProperties();
            JSONObject finalValues = values;
            featureProperties.forEach(f -> {
                String name = f.getString("name");
                String code = f.getString("code");
                Object o = theJsonObject.get(code);
                finalValues.put(name, o);
            });
            hierInstance.setValues(finalValues);
        }
        return hierInstance;
    }

    /**
     * 根据nodeId，查询后续节点，即下级的prev中包括nodeId的所有元素
     * @param model
     * @param className
     * @param nodeId
     * @return
     */
    @Override
    public List<HierInstance> queryNextByNodeId(String model, String className, String nodeId) {
        QueryWrapper<HierInstance> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("containerModel", model);
        queryWrapper.eq("className", className);
        List<HierInstance> hierInstanceList = hierInstanceService.list(queryWrapper);
        return hierInstanceList.stream().filter(d->d.getPrev().contains(nodeId)).collect(Collectors.toList());
    }


    /**
     * 更改状态
     * @param id
     * @param statusCode
     */
    @Override
    public void updateStatus(Long id, String statusCode) {
        HierInstance hierInstance = getById(id);
        hierInstance.setSt0(statusCode);
        updateById(hierInstance);
    }

    /**
     * 根据model和className删除实例
     * @param model 模型
     * @param className 模型名称
     * @return
     */
    @Override
    public boolean deleteByClassName(String model, String className) {
        return hierInstanceService.removeByModelAndClassName(model, className);
    }

    /**
     * 根据linkModel和linkClassName删除实例
     * @param linkModel 关联模型
     * @param linkClassName 关联模型名称
     * @return
     */
    @Override
    public boolean deleteByLinkClassName(String linkModel, String linkClassName) {
        return hierInstanceService.removeByLinkModelAndLinkClassName(linkModel, linkClassName);
    }

    /**
     * 删除实例
     *
     * @param idList 模型id 删除模型
     * @return
     */
    @Override
    public boolean deleteByIdList(List<Long> idList) {
        return hierInstanceService.removeBatchByIds(idList);
    }

    /**
     * 删除实例
     *
     * @param id 模型id 删除模型
     * @return
     */
    @Override
    public boolean deleteById(Long id) {
        return hierInstanceService.removeById(id);
    }

    /**
     * 根据model和className数组删除实例
     * @param model 删除模型
     * @param classNameList
     * @return
     */
    @Override
    public boolean deleteByClassNameList(String model, List<String> classNameList) {
        return hierInstanceService.removeByModelAndClassNameList(model, classNameList);
    }

    /**
     * 根据linkModel和linkClassNameList数组删除实例
     * @param linkModel 关联模型
     * @param linkClassNameList 关联模型名称数组
     * @return
     */
    @Override
    public boolean deleteByLinkClassNameList(String linkModel, List<String> linkClassNameList) {
        return hierInstanceService.removeByLinkModelAndLinkClassNameList(linkModel, linkClassNameList);
    }

    /**
     * 根据model和containerId数组删除实例
     * @param model 删除模型
     * @param containerIdList
     * @return
     */
    @Override
    public boolean deleteByContainerIdList(String model, List<Long> containerIdList) {
        return hierInstanceService.removeByModelAndContainerIdList(model, containerIdList);
    }

    /**
     * 根据model和containerId删除实例
     * @param model 删除模型
     * @param containerId
     * @return
     */
    @Override
    public boolean deleteByContainerId(String model, Long containerId) {
        return hierInstanceService.removeByModelAndContainerId(model, containerId);
    }

    /**
     * 根据linkModel和linkIdList数组删除实例
     * @param linkModel 关联模型
     * @param linkIdList 关联实例id数组
     * @return
     */
    @Override
    public boolean deleteByLinkIdList(String linkModel, List<Long> linkIdList) {
        return hierInstanceService.removeByLinkModelAndLinkIdList(linkModel, linkIdList);
    }

    /**
     * 根据linkModel和linkId删除实例
     * @param linkModel 关联模型
     * @param linkId 关联实例id
     * @return
     */
    @Override
    public boolean deleteByLinkId(String linkModel, Long linkId) {
        return hierInstanceService.removeByLinkModelAndLinkId(linkModel, linkId);
    }

    /**
     * 删除实例
     *
     * @param containerId
     * @return
     */
    @Override
    public boolean deleteByParentId(String model, Long containerId, String parentNodeId) {
        return hierInstanceService.removeByParentId(model, containerId, parentNodeId);
    }

    @Override
    public HierInstance fetchByLinkClassName(String model, Long containerId, String linkClassName) {
        List<HierInstance> hierInstances = queryByContainerId(model, containerId);
        return filterNode(hierInstances, (HierInstance hi) -> linkClassName.equalsIgnoreCase(hi.getLinkClassName()));
    }

    /**
     * 构建新的实例对象
     * @param hierProperties
     * @return
     */
    private List<HierInstance> buildInstanceList(JSONObject hierProperties) {
        String containerModel = hierProperties.getString("containerModel");
        String className = hierProperties.getString("className");
        List<HierModel> modelList = hierModelService.queryByModelAndClassName(containerModel, className);
        if (CollectionUtil.isEmpty(modelList)) {
            return Collections.emptyList();
        }
        List<HierInstance> instanceList = buildInstanceList(hierProperties, modelList);
        return instanceList;
    }

    /**
     * 查询条件字段转换
     *
     * @param condition 参数
     * @param className 参数
     */
    public String transformConditionForHier(String model, String className, String parentId, String condition) {
        if (StringUtils.isBlank(condition)) {
            return "";
        }
        if (StringUtils.isBlank(className)) {
            className = queryBuilder.getClassNameBy(condition);
        }
        if (StringUtils.isBlank(className)) {
            return condition;
        }
        if (StringUtils.isNotBlank(className) && StringUtils.isNotBlank(condition)) {
            HierModel hierModel = fetchFirstHierModelWithProperty(model, className, parentId);
            if (hierModel != null) {
                List<JSONObject> featureProperties = hierModel.fetchFeatureProperties();
                for (JSONObject item : featureProperties) {
                    String name = item.getString("name");
                    String code = item.getString("code");
                    condition = condition.replaceAll("(?<!['%a-z\\d_\\u4e00-\\u9fa5])"+name, code);
                }
                List<JSONObject> featureNoProperties = hierModel.fetchNonFeaturesProperties();
                for (JSONObject item : featureNoProperties) {
                    String name = item.getString("name");
                    condition = condition.replaceAll("(?<!['%a-z0-9_\\u4e00-\\u9fa5])"+name,
                            java.util.regex.Matcher.quoteReplacement("JSON_EXTRACT(insValues,'$.")+name+
                                    "')");
                }
            }
        }
        return condition;
    }

    /**
     * 查询条件字段转换
     *
     * @param condition 取className 条件
     * @param className 类名
     * @param orderBy   排序参数
     */
    public String transformOrderByForHier(String condition, String className, String orderBy) {
        if (StringUtils.isBlank(orderBy)) {
            return "";
        }
        if (StringUtils.isBlank(className)) {
            className = queryBuilder.getClassNameBy(condition);
        }

        if (StringUtils.isBlank(className)) {
            return orderBy;
        }
        orderBy = orderBy.replaceAll(" ", "");
        HierModel hierModel = modelCacheDslService.queryModel(ModelType.Hier.getCode(), className);
        List<JSONObject> featureProperties = hierModel.fetchFeatureProperties();
        for (JSONObject item : featureProperties) {
            String name = item.getString("name");
            String code = item.getString("code");
            orderBy = orderBy.replaceAll(name, code);
        }
        return orderBy;
    }


    /**
     * 构建HierInstanceList
     * @param hierProperties
     * @param modelList
     * @return
     */
    private List<HierInstance> buildInstanceList(JSONObject hierProperties, List<HierModel> modelList) {
        List<HierInstance> instanceList = new ArrayList<>();
        String containerModel = hierProperties.getString("containerModel");
        String containerId = hierProperties.getString("containerId");
        String className = hierProperties.getString("className");
        String type = hierProperties.getString("type");
        JSONArray contentArray = hierProperties.getJSONArray("content");
        for (int i = 0; i < contentArray.size(); i++) {
            JSONObject content = contentArray.getJSONObject(i);
            HierInstance instance = buildNewInstance(containerModel, containerId, className, modelList, type, content);
            instanceList.add(instance);
        }
        return instanceList;
    }

    /**
     * 构建instance
     * @param containerModel
     * @param containerId
     * @param className
     * @param modelList
     * @param type
     * @param content
     * @return
     */
    private HierInstance buildNewInstance(String containerModel, String containerId, String className, List<HierModel> modelList, String type, JSONObject content) {
        JSONObject insJsonObject = new JSONObject();
        String nodeId = content.getString("nodeId");
        insJsonObject.put("containerModel", containerModel);
        insJsonObject.put("className", className);
        insJsonObject.put("containerId", containerId);
        insJsonObject.put("type", content.getString("type"));
        insJsonObject.put("name", content.getString("name"));
        insJsonObject.put("nodeId", nodeId);
        insJsonObject.put("parentId", content.getString("parentId"));
        insJsonObject.put("prev", content.getJSONArray("prev"));
        insJsonObject.put("nodeType", content.getString("nodeType"));
        insJsonObject.put("values", content.getJSONObject("values"));
        JSONObject linkJson = content.getJSONObject("link");
        if (linkJson != null) {
            insJsonObject.put("linkModel", linkJson.getString("linkModel"));
            insJsonObject.put("linkClassName", linkJson.getString("linkClassName"));
            insJsonObject.put("linkType", linkJson.getString("linkType"));
            insJsonObject.put("linkId", linkJson.getString("linkId"));
        }
        // 处理list与非list的情况, list无nodeId， 其他情况应该都有nodeId， 已便model与hier能够关联
        HierModel hierModel = modelList.get(0);
        if (!"list".equals(type)) {
            hierModel = modelList.stream().filter(d->nodeId.equals(d.getNodeId())).findFirst().orElseThrow(
                    () -> new BusinessException("缺少NodeId")
            );
        }
        HierInstance instance = buildNewInstance(hierModel, insJsonObject);
        return instance;
    }




    /**
     * 完全根据指定的model生成实例
     * @param hierModel， 必须包含containerId
     * @param dataJson
     * @return
     */
    public HierInstance buildNewInstanceByModelAndJson(HierModel hierModel, JSONObject dataJson) {
        JSONObject insJsonObject = new JSONObject();
        insJsonObject.put("containerModel", hierModel.getModel());
        insJsonObject.put("className", hierModel.getClassName());
        insJsonObject.put("containerId", dataJson.getLong("containerId"));
        insJsonObject.put("type", hierModel.getType());
        insJsonObject.put("name", dataJson.getString("name"));
        insJsonObject.put("nodeId", dataJson.getString("nodeId"));
        insJsonObject.put("parentId", dataJson.getString("parentId"));
        insJsonObject.put("prev", dataJson.getJSONArray("prev"));
        insJsonObject.put("nodeType", dataJson.getString("nodeType"));
        insJsonObject.put("values", dataJson.getJSONObject("values"));
        JSONObject linkJson = dataJson.getJSONObject("link");
        if (linkJson != null) {
            insJsonObject.put("linkModel", linkJson.getString("linkModel"));
            insJsonObject.put("linkClassName", linkJson.getString("linkClassName"));
            insJsonObject.put("linkType", linkJson.getString("linkType"));
            insJsonObject.put("linkId", linkJson.getString("linkId"));
        }
        HierInstance instance = buildNewInstance(hierModel, insJsonObject);
        return instance;
    }




    /**
     * 添加历史数据
     * @param instanceList
     */
    private void addHistory(List<HierInstance> instanceList) {
        if (CollectionUtil.isEmpty(instanceList)) {
            return;
        }
        //添加历史
        List<HierInstance> newInstanceList = hierInstanceService.listByIds(instanceList.stream().map(d->d.getId()).collect(Collectors.toList()));
        List<HierInstanceHistory> hierInstanceHistoryList = BeanUtil.copyToList(newInstanceList, HierInstanceHistory.class);
        hierInstanceHistoryList.forEach(d->d.setId(null));
        hierInstanceHistoryService.saveBatch(hierInstanceHistoryList);
    }

    /**
     * 查询指定节container下的节点的值
     * @param parentInstance
     * @return
     */
    @Override
    public <T> T fetchValue(HierInstance parentInstance, String nodeName, String path) {
        List<HierInstance> instanceList = fetchAllNode(parentInstance.getContainerModel(), parentInstance.getClassName(), parentInstance.getContainerId());
        HierInstance hierInstance = filterNode(instanceList, d -> d.getName().equals(nodeName));
        return fetchValue(hierInstance, path);
    }

    /**
     * 获取指定容器的所有node节点
     * @param model
     * @param containerId
     * @return
     */
    @Override
    public HierInstance fetchByLinkId(String model, Long containerId, Long linkId) {
        List<HierInstance> instanceList = fetchAllNode(model, containerId);
        Predicate<HierInstance> predicate = p -> linkId.equals(p.getLinkId());
        return filterNode(instanceList, predicate);
    }

    /**
     * 获取指定容器的所有node节点
     * @param model
     * @param className
     * @param containerId
     * @return
     */
    @Override
    public HierInstance fetchByNodeId(String model, String className, Long containerId, String nodeId) {
        List<HierInstance> instanceList = fetchAllNode(model, className, containerId);
        if (CollectionUtil.isEmpty(instanceList)) {
            return null;
        }
        Predicate<HierInstance> predicate = p -> nodeId.equals(p.getNodeId());
        return filterNode(instanceList, predicate);
    }

    /**
     * 获取指定容器的所有node节点
     * @param model
     * @param containerId
     * @return
     */
    @Override
    public HierInstance fetchByNodeId(String model, Long containerId, String nodeId) {
        List<HierInstance> instanceList = fetchAllNode(model, containerId);
        if (CollectionUtil.isEmpty(instanceList)) {
            return null;
        }
        // Predicate<HierInstance> predicate = p -> p.getNodeId().equals(nodeId) || "root".equals(p.getNodeId());
        Predicate<HierInstance> predicate = p -> p.getNodeId().equals(nodeId);
        return filterNode(instanceList, predicate);
    }

    /**
     * 根据父节点ID， 获取所有子节点
     * @param model
     * @param containerId
     * @return
     */
    @Override
    public List<HierInstance> fetchByParentNodeId(String model, Long containerId, String parentNodeId) {
        List<HierInstance> instanceList = fetchAllNode(model, containerId);
        Predicate<HierInstance> predicate = p -> p.getParentId().equals(parentNodeId);
        return filterNodeList(instanceList, predicate);
    }

    /**
     * 根据父节点ID， 获取所有子节点
     * @param model
     * @param containerId
     * @return
     */
    @Override
    public Map<Object, List<HierInstance>> fetchByParentNodeIdAndGroupBy(String model, Long containerId, String parentNodeId, String groupByKey) {
        List<HierInstance> instanceList = fetchAllNode(model, containerId);
        Predicate<HierInstance> predicate = p -> p.getParentId().equals(parentNodeId);
        List<HierInstance> hierInstanceList = filterNodeList(instanceList, predicate);
        // 将查询字段也存放到values中
        List<HierInstance> hierInstanceWithValueList = convertValuesByProperty(hierInstanceList);
        Map<Object, List<HierInstance>> resultMap = hierInstanceWithValueList.stream()
                .collect(Collectors.groupingBy(d->d.getValues().get(groupByKey)));
        return resultMap;
    }




    /**
     * 获取指定容器,指定名称的节点，如：查找workCenter中的material节点
     * @param model
     * @param className
     * @param containerId
     * @return
     */
    @Override
    public List<HierInstance> fetchByName(String model, String className, Long containerId, String name) {
        List<HierInstance> instanceList = fetchAllNode(model, className, containerId);
        Predicate<HierInstance> predicate = p -> p.getName().equals(name);
        return filterNodeList(instanceList, predicate);
    }

    /**
     * 获取指定容器,指定ParentId下的节点
     * @param model
     * @param className
     * @param containerId
     * @param parentId
     * @return
     */
    @Override
    public List<HierInstance> fetchByParentId(String model, String className, Long containerId, String parentId) {
        List<HierInstance> instanceList = fetchAllNode(model, className, containerId);
        Predicate<HierInstance> predicate = p -> p.getParentId().equals(parentId);
        return filterNodeList(instanceList, predicate);
    }

    /**
     * 获取指定容器的所有node节点
     * @param model
     * @param containerId
     * @return
     */
    @Override
    public List<HierInstance> fetchAllNode(String model, Long containerId) {
        return queryByContainerId(model, containerId);
    }

    /**
     * 获取指定容器的所有node节点
     * @param model
     * @param className
     * @param containerId
     * @return
     */
    @Override
    public List<HierInstance> fetchAllNode(String model, String className, Long containerId) {
        return queryByContainerId(model, className, containerId);
    }

    /**
     * 获取所有node节点
     * @param model
     * @param className
     * @param containerId
     * @return
     */
    @Override
    public List<HierInstance> fetchAllNode(String model, String className, Long containerId, Predicate<HierInstance> predicate) {
        List<HierInstance> instanceList = queryByContainerId(model, className, containerId);
        return  filterNodeList(instanceList, predicate);
    }

    /**
     * 获取所有node节点
     * @param model
     * @param containerId
     * @return
     */
    @Override
    public List<HierInstance> fetchAllNode(String model, Long containerId, Predicate<HierInstance> predicate) {
        List<HierInstance> instanceList = queryByContainerId(model, containerId);
        return  filterNodeList(instanceList, predicate);
    }

    @Override
    public List<HierInstance> filterNodeList(List<HierInstance> hierInstanceList, Predicate<HierInstance> predicate) {
        return hierInstanceList.stream().filter(predicate).collect(Collectors.toList());
    }

    @Override
    public HierInstance filterNode(List<HierInstance> hierInstanceList, Predicate<HierInstance> predicate) {
        Optional<HierInstance> optional = hierInstanceList.stream().filter(predicate).findFirst();
        return optional.orElse(null);
    }

    /**
     * 获取value中指定的name的值
     * @param instance
     * @param path
     * @param <T>
     * @return
     */
    @Override
    public  <T> T fetchValue(HierInstance instance, String path) {
        JSONObject values = instance.getValues();
        return JsonUtil.get(values, path);
    }

    @Override
    public Map<String, Object> fetchLink(HierInstance instance) {
        HashMap<String, Object> resultMap = new HashMap<>();
        resultMap.put("linkModel", instance.getLinkModel());
        resultMap.put("linType", instance.getLinkType());
        resultMap.put("linkClassName", instance.getLinkClassName());
        resultMap.put("linkId", instance.getLinkId());
        return resultMap;
    }


    /**
     * 查询instance的condition条件
     * @param workCenterId
     * @return
     */
    @Override
    public String fetchCondition(Long workCenterId) {
        HierInstance hierInstance = hierInstanceService.getById(workCenterId);
        String condition = fetchValue(hierInstance, "createInsFlag", "condition");
        return condition;
    }

    /**
     * 查询instance的condition条件
     * @param workCenterInstanceList
     * @return Map<Long, String> key=workCenterId， value=condition
     */
    @Override
    public Map<Long, String> fetchCondition(List<HierInstance> workCenterInstanceList) {
        Map<Long, String> resultMap = new HashMap<>();
        workCenterInstanceList.forEach(instance->{
            String condition = fetchValue(instance, "createInsFlag", "condition");
            resultMap.put(instance.getId(), condition);
        });
        return resultMap;
    }


    /**
     * 查询instance的createInsFlag
     * @param workCenterId
     * @return
     */
    @Override
    public Boolean fetchCreateInsFlag(Long workCenterId) {
        HierInstance hierInstance = hierInstanceService.getById(workCenterId);
        Boolean flag = fetchValue(hierInstance, "createInsFlag", "createInsFlag");
        return flag;
    }

    @Override
    public HierInstance getById(Long hierInstanceId) {
        return  hierInstanceService.getById(hierInstanceId);
    }


    /**
     * 获取当前节点的后一级需要激活的节点集合
     * @param currentInstance
     * @param predicateCondition 判断条件的断言
     * @return
     */
    @Override
    public List<HierInstance> fetchToReadyNodeList(HierInstance currentInstance, Predicate<String> predicateCondition) {
        // 后一级节点集合
        List<HierInstance> nextInstanceList = queryNextByNodeId(currentInstance.getContainerModel(), currentInstance.getClassName(), currentInstance.getNodeId());
        List<HierInstance> resultList = new ArrayList<>();
        nextInstanceList.forEach(instance->{
            String condition = fetchValue(instance, "condition");
            boolean conditionFlag = predicateCondition.test(condition);
            if (conditionFlag) {
                instance.setSt0(RoutingStatusEnum.READY.getCode());
                resultList.add(instance);
            }
        });
        return resultList;
    }

    /**
     * 激活后续节点
     * @param hierInstance
     * @param predicateCondition
     */
    @Override
    public void updateNodeListToReady(HierInstance hierInstance, Predicate<String> predicateCondition) {
        List<HierInstance> hierInstanceToReadyList = fetchToReadyNodeList(hierInstance, predicateCondition);
        updateBatchById(hierInstanceToReadyList);
    }

    /**
     * 更新节点状态
     * @param containerModel
     * @param containerId
     * @param nodeId
     * @param statusCode
     * @return
     */
    @Override
    public HierInstance updateStatus(String containerModel, Long containerId, String nodeId, String statusCode) {
        HierInstance hierInstance = fetchByNodeId(containerModel, containerId, nodeId);
        hierInstance.setSt0(statusCode);
        return updateById(hierInstance);
    }


    @Override
    public boolean updateOccupyStatus(String containerModel, Long containerId, List<String> nodeIdList, String statusCode) {
        List<HierInstance> instanceList = fetchByNodeList(containerModel, containerId, nodeIdList);
        instanceList.forEach(d->d.setSt1(statusCode));
        return updateBatchById(instanceList);
    }

    private List<HierInstance> fetchByNodeList(String containerModel, Long containerId, List<String> nodeIdList) {
        List<HierInstance> instanceList = fetchAllNode(containerModel, containerId);
        Predicate<HierInstance> predicate = p -> nodeIdList.contains(p.getNodeId());
        return filterNodeList(instanceList, predicate);
    }

    @Override
    public boolean updateClassName(String model, String className, String oldClassName) {
        List<HierInstance> instanceList = hierInstanceService.queryByModelAndClassName(model, oldClassName);
        instanceList.forEach(d-> d.setClassName(className));
        return updateBatchById(instanceList);
    }

    /**
     * 结合新的model，构建新的实例
     * @param hierModel
     * @param jsonObject
     * @return
     */
    public HierInstance buildNewInstance(HierModel hierModel, JSONObject jsonObject){
        JSONObject allValues = jsonObject.getJSONObject("values");
        if(hierModel.getProperties() != null){
            JSONObject nonFeatures = hierModel.fetchNonFeatures();
            JSONObject nonValues = JsonUtil.merge(nonFeatures, allValues);
            List<JSONObject> featureProperties = hierModel.fetchFeatureProperties();
            featureProperties.forEach(f->{
                String name = f.getString("name");
                String code = f.getString("code");
                Object defaultValue = f.get("defaultValue");
                if(allValues != null && allValues.containsKey(name)){
                    jsonObject.put(code,allValues.get(name));
                }else{
                    jsonObject.put(code,defaultValue);
                }
            });
            jsonObject.put("values",nonValues);
        }else{
            jsonObject.put("values",new JSONObject());
        }

        if(hierModel.getStatusProperties() != null){
            hierModel.getStatusProperties().forEach(st->{
                JSONObject item = JSONObject.parseObject(JSON.toJSONString(st));
                String code = item.getString("code");
                Object defaultValue = item.get("defaultValue");
                jsonObject.put(code,defaultValue);
            });
        }

        HierInstance instance = JsonUtil.toJavaBean(jsonObject, HierInstance.class);
        return instance;
    }

    /**
     * 根据新老模型，构建新的实例数据
     * @param newModel
     * @param oldModel
     * @param oldInstanceList
     * @return
     */
    private List<HierInstance> dealInstanceList(HierModel newModel, HierModel oldModel, List<HierInstance> oldInstanceList) {
        List<HierInstance> oldInstanceJsonList = convertValuesByProperty(oldInstanceList, oldModel);
        Map<String, JSONObject> newFeatureMap = newModel.fetchFeatureMap();
        JSONObject newNonFeatureJson = newModel.fetchNonFeatures();
        // 将values中的数据根据名称进行合并
        List<HierInstance> newInstanceList = oldInstanceJsonList.stream().map(oldInstanceJson -> {
            HierInstance newInstanceJson = BeanUtil.copyProperties(oldInstanceJson, HierInstance.class);
            JSONObject newValuesJson = new JSONObject();
            // 先将所有值都设置为新模型的默认值
            newFeatureMap.forEach((k,v) -> newValuesJson.put(k, v.get("defaultValue")));
            newNonFeatureJson.forEach((k,v) -> newValuesJson.put(k, v));
            JSONObject oldValuesJson = oldInstanceJson.getValues();
            oldValuesJson.forEach((name, value) -> {
                // 如果在新模型中存在该字段，则保留原来的值
                if (newFeatureMap.containsKey(name) || newNonFeatureJson.containsKey(name)) {
                    newValuesJson.put(name, value);
                }
            });
            newInstanceJson.setValues(newValuesJson);
            return newInstanceJson;
        }).collect(Collectors.toList());
        return newInstanceList;
    }

    /**
     * 根据新老模型，拿到需要更新的实例数据
     * @param oldHierModelList
     * @param newHierModelList
     * @return
     */
    private List<HierInstance> buildUpdateInstanceList(List<HierModel> oldHierModelList, List<HierModel> newHierModelList) {
        List<HierInstance> newInstanceList = new ArrayList<>();
        Map<String, HierModel> newHierModelMap = newHierModelList.stream().collect(Collectors.toMap(d -> d.getNodeId(), d -> d));
        oldHierModelList.forEach(oldHierModel->{
            List<HierInstance> oldInstanceList = hierInstanceService.queryByModelAndClassName(oldHierModel.getModel(), oldHierModel.getClassName());
            oldInstanceList = oldInstanceList.stream().filter(d->d.getParentId()!=null && d.getParentId().equals(oldHierModel.getNodeId())).collect(Collectors.toList());
            // 根据nodeId去判断是否属于一个hierModel
            HierModel newHierModel = newHierModelMap.get(oldHierModel.getNodeId());
            if (newHierModel == null) {
                // 说明新模型中该节点被删除了，应该将实例数据也删除
                oldInstanceList.forEach(d -> d.setDeleteFlag(true));
                hierInstanceService.updateBatchById(oldInstanceList);
            } else {
                // 说明新模型中还需要保留数据
                if (newHierModel != null && CollectionUtil.isNotEmpty(oldHierModel.getProperties()) && CollectionUtil.isNotEmpty(newHierModel.getProperties())) {
                    List<HierInstance> tempNewInstanceList = dealInstanceList(newHierModel, oldHierModel, oldInstanceList);
                    newInstanceList.addAll(tempNewInstanceList);
                }
            }
        });
        return newInstanceList;
    }


    //region ******************针对新项目“泰正”的方法*****************
    @Override
    public HierInstance saveOrUpdate(HierInstance hierInstance) {
        hierInstanceService.saveOrUpdate(hierInstance);
//        addHistory(Arrays.asList(hierInstance));
        return hierInstance;
    }

    @Override
    public List<HierInstance> saveOrUpdateBatch(List<HierInstance> hierInstanceList) {
        hierInstanceService.saveOrUpdateBatch(hierInstanceList);
//        addHistory(hierInstanceList);
        return hierInstanceList;
    }

    /**
     * 给指定的节点，增加子节点，heierModel以最近一级的父节点为准
     * 批量增加时，所有子节点默认是一个父节点
     * @param hierInstanceJsonList
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addBatchChildBySameParent(List<JSONObject> hierInstanceJsonList) {
        JSONObject hierInstanceJson = hierInstanceJsonList.get(0);
        Long containerId = hierInstanceJson.getLong("containerId");
        String containerModel = hierInstanceJson.getString("containerModel");
        String parentNodeId = hierInstanceJson.getString("parentId");
        HierInstance parentHierInstance = fetchByNodeId(containerModel, containerId, parentNodeId);
        if (parentHierInstance == null) {
            throw new BusinessException(StatusCode.ERROR_DATA_ERROR.getCode(), "父节点不存在");
        }
        HierModel parentHierModel = fetchFirstHierModelWithProperty(parentHierInstance);
        hierInstanceJsonList.forEach(hierJson -> {
            addChild(hierJson, parentHierInstance, parentHierModel);
        });
    }

    @Override
    public void addChild(List<JSONObject> hierInstanceJsonList) {
        hierInstanceJsonList.forEach(hierInstanceJson ->addChild(hierInstanceJson));
    }

    /**
     * 给指定的节点，增加子节点，heierModel以最近一级的父节点为准
     * 增加节点和更新节点
     * @param hierInstanceJson
     * @return
     */
    @Override
    public HierInstance addChild(JSONObject hierInstanceJson) {
        Long containerId = hierInstanceJson.getLong("containerId");
        String containerModel = hierInstanceJson.getString("containerModel");
        String parentNodeId = hierInstanceJson.getString("parentId");
        HierInstance parentHierInstance = fetchByNodeId(containerModel, containerId, parentNodeId);
        if (parentHierInstance == null) {
            throw new BusinessException(StatusCode.ERROR_DATA_ERROR.getCode(), "父节点不存在");
        }
        HierModel parentHierModel = fetchFirstHierModelWithProperty(parentHierInstance);
        HierInstance hierInstance = addChild(hierInstanceJson, parentHierInstance, parentHierModel);
        return convertValuesByProperty(hierInstance, parentHierModel);
    }

    private HierInstance addChild(JSONObject hierInstanceJson, HierInstance parentHierInstance, HierModel parentHierModel) {
        List<JSONObject> featureProperties = parentHierModel.fetchFeatureProperties();
        JSONObject hierValuesJson = hierInstanceJson.getJSONObject("values");
        featureProperties.forEach(f->{
            Object filedValue = hierValuesJson.get(f.getString("name"));
            hierInstanceJson.put(f.getString("code"),
                    filedValue == null? f.get("defaultValue") :filedValue);
            if (filedValue != null) {
                hierValuesJson.remove(f.getString("name"));
            }
        });
        HierInstance hierInstance = JsonUtil.toJavaBean(hierInstanceJson, HierInstance.class);
        // 执行到这里时，hierValuesJson 中剩下的全都是非查询字段
        JSONObject nonFeatureValues = parentHierModel.fetchNonFeatureValues();
        JSONObject nonFeatureTypeJson = parentHierModel.fetchNonFeatureTypeProperties();
        hierValuesJson.forEach((k,v)->{
            Object newValue = DaoUtil.ConvertFieldData(hierValuesJson.getString(k), nonFeatureTypeJson.getString(k));
            nonFeatureValues.put(k, newValue);
        });
        // BeanUtil.copyProperties(hierValuesJson, nonFeatureValues);
        hierInstance.setValues(nonFeatureValues);
        hierInstance.setType(parentHierInstance.getType());
        String uuid32 = UuidTool.getUUID32();
        String name = hierInstanceJson.getString("name");
        hierInstance.setName(StrUtil.isNotBlank(name)? name:uuid32);
        hierInstance.setClassName(parentHierInstance.getClassName());
        hierInstance.setParentId(parentHierInstance.getNodeId());
        String nodeType = hierInstanceJson.getString("nodeType");
        hierInstance.setNodeType(StrUtil.isNotBlank(nodeType)? nodeType:"leaf");
        String nodeId = hierInstanceJson.getString("nodeId");
        hierInstance.setNodeId(StrUtil.isNotBlank(nodeId)? nodeId:uuid32);
        //代入父节点的link相关模型信息
        hierInstance.setLinkModel(StrUtil.isNotBlank(hierInstanceJson.getString("linkModel"))? hierInstanceJson.getString("linkModel"): parentHierInstance.getLinkModel());
        hierInstance.setLinkClassName(StrUtil.isNotBlank(hierInstanceJson.getString("linkClassName"))? hierInstanceJson.getString("linkClassName"):parentHierInstance.getLinkClassName());
        hierInstance.setLinkType(StrUtil.isNotBlank(hierInstanceJson.getString("linkType"))? hierInstanceJson.getString("linkType"):parentHierInstance.getLinkType());
        hierInstance.setLinkId(hierInstanceJson.getLong("linkId"));
        hierInstanceService.saveOrUpdate(hierInstance);
        addHistory(Arrays.asList(hierInstance));
        return hierInstance;
    }


    /**
     * 添加一个子节点，父子节点唯一不同的就是LinkId不同，其他全相同
     * @param containerId
     * @param parentLinkModel
     * @param parentLinkClassName
     * @param linkId
     * @return
     */
    @Override
    public HierInstance saveChild(Long containerId, String parentLinkModel,
                                        String parentLinkClassName, Long linkId) {
        HierInstance hierInstance = buildNewInstance(containerId, parentLinkModel, parentLinkClassName, linkId);
        return saveOrUpdate(hierInstance);
    }


    /**
     * 添加子节点，父子节点唯一不同的就是LinkId不同，其他全相同
     * @param containerId
     * @param parentLinkModel
     * @param parentLinkClassName
     * @param linkIdList
     * @return
     */
    @Override
    public List<HierInstance> saveChildBatch(Long containerId, String parentLinkModel,
                                        String parentLinkClassName, List<Long> linkIdList) {
        List<HierInstance> hierInstanceList = buildNewInstanceList(containerId, parentLinkModel, parentLinkClassName, linkIdList);
        return saveOrUpdateBatch(hierInstanceList);
    }

    public HierInstance buildNewInstance(Long containerId, String parentLinkModel, String parentLinkClassName, Long linkId) {
        HierInstance hierInstance = fetchByLinkClassName(parentLinkModel, containerId, parentLinkClassName);
        hierInstance.setId(null);
        hierInstance.setLinkId(linkId);
        hierInstance.setName(UuidTool.getUUID32());
        hierInstance.setNodeId(UuidTool.getUUID32());
        hierInstance.setParentId(hierInstance.getNodeId());
        hierInstance.setNodeType("leaf");
        return hierInstance;
    }

    public List<HierInstance> buildNewInstanceList(Long containerId, String parentLinkModel, String parentLinkClassName, List<Long> linkIdList) {
        HierInstance hierInstance = fetchByLinkClassName(parentLinkModel, containerId, parentLinkClassName);
        return linkIdList.stream().map(d->{
                    hierInstance.setId(null);
                    hierInstance.setLinkId(d);
                    hierInstance.setName(UuidTool.getUUID32());
                    hierInstance.setNodeId(UuidTool.getUUID32());
                    hierInstance.setParentId(hierInstance.getNodeId());
                    hierInstance.setNodeType("leaf");
                    return hierInstance;
                }
        ).collect(Collectors.toList());

    }

    /**
     * 给List节点下Link数据
     * @param data
     * @return
     */
    @Override
    public List<HierInstance>  addNodeAndLinkInstanceToListContainer(JSONObject data){
        String model = data.getString("model");
        long containerId = data.getLong("containerId");
        String parentNodeId = data.getString("parentNodeId");
        JSONArray dataArray = data.getJSONArray("dataArray");
        HierInstance parentHierInstance = fetchByNodeId(model, containerId, parentNodeId);
        List<HierInstance> childHierInstanceList = buildHierInstanceListByParent(dataArray, parentHierInstance);
        return saveOrUpdateBatch(childHierInstanceList);
    }

    @Override
    public boolean deleteNodeByLink(JSONObject data) {
        String model = data.getString("model");
        long containerId = data.getLong("containerId");
        String parentNodeId = data.getString("parentNodeId");
        List<HierInstance> hierInstanceList = fetchByParentNodeId(model, containerId, parentNodeId);
        JSONArray linkDataArray = data.getJSONArray("linkDataArray");
        List<HierInstance> deleteList = filterNodeListByLink(hierInstanceList, linkDataArray);
        return hierInstanceService.removeBatchByIds(deleteList.stream().map(HierInstance::getId).collect(Collectors.toList()));
    }

    public List<HierInstance> filterNodeListByLink(List<HierInstance> hierInstanceList, JSONArray linkDataArray) {
        List<HierInstance> resultHierInstanceList = new ArrayList<>();
        for (int i = 0; i < linkDataArray.size(); i++) {
            JSONObject linkData = linkDataArray.getJSONObject(i);
            List<HierInstance> tempHierInstanceList = filterNodeList(hierInstanceList, (HierInstance hierInstance) ->
                    hierInstance.getLinkId() != null && hierInstance.getLinkId().equals(linkData.getLong("linkId")) &&
                            StrUtil.isNotBlank(hierInstance.getLinkModel()) && hierInstance.getLinkModel().equals(linkData.getString("linkModel")) &&
                            StrUtil.isNotBlank(hierInstance.getLinkClassName()) && hierInstance.getLinkClassName().equals(linkData.getString("linkClassName")) &&
                            StrUtil.isNotBlank(hierInstance.getLinkType()) && hierInstance.getLinkType().equals(linkData.getString("linkType")
                    ));
            resultHierInstanceList.addAll(tempHierInstanceList);
        }
        return resultHierInstanceList;
    }




    private List<HierInstance> buildHierInstanceListByParent(JSONArray dataArray, HierInstance parentHierInstance) {
        if (parentHierInstance == null) {
            throw new BusinessException(StatusCode.ERROR_DATA_ERROR.getCode(), "父节点不存在");
        }
        List<JSONObject> dataJsonList = dataArray.toJavaList(JSONObject.class);
        List<HierInstance> instanceList = buildChildInstanceList(parentHierInstance.getContainerModel(),
                parentHierInstance.getClassName(), parentHierInstance.getContainerId(), parentHierInstance.getNodeId(),
                dataJsonList);
        return instanceList;
    }


    /**
     * 从查询条件中解析出className 值
     *
     * @param condition 查询条件
     * @return 返回结果
     */
    private String getParentIdBy(String condition) {
        if (StringUtils.isBlank(condition)) {
            return null;
        }
        String s = condition.replaceAll("==", "=").replaceAll(" ", "");
        int start = s.indexOf("parentId='");
        String parentId = null;
        if (start < 0) {
            return null;
        }
        String parentIdOpt = s.substring(start + "parentId='".length());
        int end = parentIdOpt.indexOf("'");

        //匹配中文，英文字母和数字及下划线
        String reg1 = "^[a-zA-Z\\d_\\u4e00-\\u9fa5]+$";
        Pattern pattern = Pattern.compile(reg1);
        Matcher matcher = pattern.matcher(parentIdOpt.substring(0, end));
        if (matcher.matches()) {
            parentId = parentIdOpt.substring(0, end);
        }
        return parentId;
    }

    @Override
    public List<HierInstance> updateByIds(JSONObject data) {
        List<HierInstance> resultList = new ArrayList<>();
        JSONArray ids = data.getJSONArray("ids");
        JSONObject values = data.getJSONObject("values");
        for (int i = 0; i < ids.size(); i++) {
            Long id = ids.getLong(i);
            HierInstance hierInstance = new HierInstance(id, ObjectUtil.cloneByStream(values));
            HierInstance result = updateById(hierInstance);
            resultList.add(result);
        }
        return resultList;
    }

    /**
     * 只是转换Json, 不会根据模型进行计算
     */
    @Override
    public JSONObject convertToJson(HierInstance instance){
        JSONObject JsonObject = new JSONObject();
        JsonObject.put("id", instance.getId());
        JsonObject.put("linkModel", instance.getLinkModel());
        JsonObject.put("linkId", instance.getLinkId());
        JsonObject.put("linkType", instance.getLinkType());
        JsonObject.put("linkClassName", instance.getLinkClassName());
        JsonObject.put("parentId", instance.getParentId());
        JsonObject.put("nodeId", instance.getNodeId());
        JsonObject.put("containerId", instance.getContainerId());
        JsonObject.put("containerModel", instance.getContainerModel());
        JsonObject.put("type", instance.getType());
        JsonObject.put("name", instance.getName());
        JsonObject.put("className", instance.getClassName());
        JsonObject.put("createdBy", instance.getCreatedBy());
        JsonObject.put("createTime", instance.getCreateTime());
        JsonObject.put("updatedBy", instance.getUpdatedBy());
        JsonObject.put("updateTime", instance.getUpdateTime());
        JsonObject.put("values", instance.getValues());
        return JsonObject;
    }

    @Override
    public List<JSONObject> convertToJson(List<HierInstance> list){
        return list.stream().map(d->convertToJson(d)).collect(Collectors.toList());
    }

    //endregion

}
